#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file config.py
@brief 配置管理模块
@details 负责管理串口参数、电机参数等配置信息
@author Motor Controller Team
@date 2024
"""

import json
import os
import logging
from typing import Dict, Any, Optional
from dataclasses import dataclass, asdict

logger = logging.getLogger(__name__)


@dataclass
class SerialConfig:
    """
    @brief 串口配置类
    @details 存储串口通信相关参数
    """
    port: str = 'COM4'           # 串口端口
    baudrate: int = 9600         # 波特率
    device_id: int = 1           # 设备ID
    timeout: float = 1.0         # 超时时间(秒)
    bytesize: int = 8            # 数据位
    parity: str = 'N'            # 校验位
    stopbits: int = 1            # 停止位


@dataclass
class UARTConfig:
    """
    @brief UART串口配置类
    @details 存储UART串口通信相关参数，专门用于日志监控
    """
    port: str = 'COM3'           # UART串口端口
    baudrate: int = 115200       # 波特率
    timeout: float = 1.0         # 超时时间(秒)
    bytesize: int = 8            # 数据位
    parity: str = 'N'            # 校验位
    stopbits: int = 1            # 停止位


@dataclass
class MotorConfig:
    """
    @brief 电机配置类
    @details 存储电机相关参数
    """
    left_motor_max_speed: int = 1000     # 左电机最大转速
    right_motor_max_speed: int = 1000    # 右电机最大转速
    left_motor_min_speed: int = 0        # 左电机最小转速
    right_motor_min_speed: int = 0       # 右电机最小转速
    default_speed: int = 500             # 默认转速
    acceleration: int = 100              # 加速度
    deceleration: int = 100              # 减速度
    system_mode: str = 'independent_speed_closed_loop'  # 系统模式


@dataclass
class AppConfig:
    """
    @brief 应用程序配置类
    @details 存储完整的应用程序配置
    """
    serial: SerialConfig = None      # Modbus串口配置（用于电机控制）
    uart: UARTConfig = None          # UART串口配置（用于日志监控）
    motor: MotorConfig = None        # 电机配置
    
    def __post_init__(self):
        """初始化后处理"""
        if self.serial is None:
            self.serial = SerialConfig()
        if self.uart is None:
            self.uart = UARTConfig()
        # 电机配置不设置默认值，由用户通过界面动态设置


class ConfigManager:
    """
    @brief 配置管理器类
    @details 负责配置的加载、保存和管理
    """
    
    def __init__(self, config_file: str = "motor_controller_config.json"):
        """
        @brief 初始化配置管理器
        @param config_file 配置文件路径
        """
        self.config_file = config_file
        self.motor_config_file = "config/motor_config.json"
        self.uart_config_file = "config/uart_config.json"
        self.config = AppConfig()
        self.load_config()
        
        logger.info(f"配置管理器初始化完成，配置文件: {config_file}")
    
    def load_config(self) -> bool:
        """
        @brief 加载配置文件
        @return bool 加载是否成功
        @retval True 加载成功
        @retval False 加载失败
        """
        try:
            # 加载串口配置
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    config_data = json.load(f)
                
                if 'serial' in config_data:
                    self.config.serial = SerialConfig(**config_data['serial'])
                    logger.info("串口配置文件加载成功")
                else:
                    logger.warning("串口配置文件中未找到serial配置")
            else:
                logger.info("串口配置文件不存在，使用默认配置")
            
            # 动态加载电机配置（如果存在）
            self.load_motor_config()
            
            # 动态加载UART配置（如果存在）
            self.load_uart_config()
            
            return True
                
        except Exception as e:
            logger.error(f"加载配置文件时发生错误: {e}")
            return False
    
    def load_motor_config(self) -> bool:
        """
        @brief 动态加载电机配置
        @return bool 加载是否成功
        """
        try:
            if os.path.exists(self.motor_config_file):
                with open(self.motor_config_file, 'r', encoding='utf-8') as f:
                    config_data = json.load(f)
                
                if 'motor' in config_data:
                    self.config.motor = MotorConfig(**config_data['motor'])
                    logger.info("电机配置文件加载成功")
                    return True
                else:
                    logger.warning("电机配置文件中未找到motor配置")
            else:
                logger.info("电机配置文件不存在，将使用动态配置")
            
            return False
                
        except Exception as e:
            logger.error(f"加载电机配置文件时发生错误: {e}")
            return False
    
    def load_uart_config(self) -> bool:
        """
        @brief 动态加载UART配置
        @return bool 加载是否成功
        """
        try:
            if os.path.exists(self.uart_config_file):
                with open(self.uart_config_file, 'r', encoding='utf-8') as f:
                    config_data = json.load(f)
                
                if 'uart' in config_data:
                    self.config.uart = UARTConfig(**config_data['uart'])
                    logger.info("UART配置文件加载成功")
                    return True
                else:
                    logger.warning("UART配置文件中未找到uart配置")
            else:
                logger.info("UART配置文件不存在，将使用默认配置")
            
            return False
                
        except Exception as e:
            logger.error(f"加载UART配置文件时发生错误: {e}")
            return False
    
    def save_config(self) -> bool:
        """
        @brief 保存串口配置文件
        @return bool 保存是否成功
        @retval True 保存成功
        @retval False 保存失败
        """
        try:
            config_data = {
                'serial': asdict(self.config.serial)
            }
            
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, indent=4, ensure_ascii=False)
            
            logger.info("串口配置文件保存成功")
            return True
            
        except Exception as e:
            logger.error(f"保存串口配置文件时发生错误: {e}")
            return False
    
    def save_motor_config(self) -> bool:
        """
        @brief 保存电机配置文件
        @return bool 保存是否成功
        @retval True 保存成功
        @retval False 保存失败
        """
        try:
            if self.config.motor is None:
                logger.warning("电机配置为空，无法保存")
                return False
            
            config_data = {
                'motor': asdict(self.config.motor)
            }
            
            with open(self.motor_config_file, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, indent=4, ensure_ascii=False)
            
            logger.info("电机配置文件保存成功")
            return True
            
        except Exception as e:
            logger.error(f"保存电机配置文件时发生错误: {e}")
            return False
    
    def save_uart_config(self) -> bool:
        """
        @brief 保存UART配置到独立文件
        @return bool 保存是否成功
        """
        try:
            if self.config.uart is None:
                logger.warning("UART配置为空，无法保存")
                return False
            
            config_data = {
                'uart': asdict(self.config.uart)
            }
            
            with open(self.uart_config_file, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, indent=4, ensure_ascii=False)
            
            logger.info("UART配置文件保存成功")
            return True
            
        except Exception as e:
            logger.error(f"保存UART配置文件时发生错误: {e}")
            return False
    
    def get_serial_config(self) -> SerialConfig:
        """
        @brief 获取串口配置
        @return SerialConfig 串口配置对象
        """
        return self.config.serial
    
    def set_serial_config(self, config: SerialConfig) -> None:
        """
        @brief 设置串口配置
        @param config 串口配置对象
        """
        self.config.serial = config
        logger.info("串口配置已更新")
    
    def get_motor_config(self) -> Optional[MotorConfig]:
        """
        @brief 获取电机配置
        @return Optional[MotorConfig] 电机配置对象，可能为None
        """
        return self.config.motor
    
    def set_motor_config(self, config: MotorConfig) -> None:
        """
        @brief 设置电机配置
        @param config 电机配置对象
        """
        self.config.motor = config
        logger.info("电机配置已更新")
    
    def get_uart_config(self) -> UARTConfig:
        """
        @brief 获取UART配置
        @return UARTConfig UART配置对象
        """
        return self.config.uart
    
    def set_uart_config(self, config: UARTConfig) -> None:
        """
        @brief 设置UART配置
        @param config UART配置对象
        """
        self.config.uart = config
        logger.info("UART配置已更新")
    
    def get_config(self) -> AppConfig:
        """
        @brief 获取完整配置
        @return AppConfig 完整配置对象
        """
        return self.config
    
    def set_config(self, config: AppConfig) -> None:
        """
        @brief 设置完整配置
        @param config 完整配置对象
        """
        self.config = config
        logger.info("完整配置已更新")
    
    def reset_to_default(self) -> None:
        """
        @brief 重置为默认配置
        """
        self.config = AppConfig()
        logger.info("配置已重置为默认值")
    
    def validate_config(self) -> Dict[str, Any]:
        """
        @brief 验证配置的有效性
        @return Dict[str, Any] 验证结果
        @retval Dict 包含验证结果的字典
        """
        errors = []
        warnings = []
        
        # 验证串口配置
        serial = self.config.serial
        if not serial.port:
            errors.append("串口端口不能为空")
        if serial.baudrate <= 0:
            errors.append("波特率必须大于0")
        if serial.device_id <= 0:
            errors.append("设备ID必须大于0")
        if serial.timeout <= 0:
            errors.append("超时时间必须大于0")
        
        # 验证电机配置
        motor = self.config.motor
        if motor.left_motor_max_speed <= 0:
            errors.append("左电机最大转速必须大于0")
        if motor.right_motor_max_speed <= 0:
            errors.append("右电机最大转速必须大于0")
        if motor.left_motor_min_speed < 0:
            errors.append("左电机最小转速不能小于0")
        if motor.right_motor_min_speed < 0:
            errors.append("右电机最小转速不能小于0")
        if motor.left_motor_min_speed >= motor.left_motor_max_speed:
            warnings.append("左电机最小转速应该小于最大转速")
        if motor.right_motor_min_speed >= motor.right_motor_max_speed:
            warnings.append("右电机最小转速应该小于最大转速")
        
        # UI配置已移除，无需验证
        
        return {
            'valid': len(errors) == 0,
            'errors': errors,
            'warnings': warnings
        }
    
    def get_available_ports(self) -> list:
        """
        @brief 获取可用的串口列表
        @return list 可用串口列表
        """
        import serial.tools.list_ports
        
        ports = []
        for port in serial.tools.list_ports.comports():
            ports.append({
                'device': port.device,
                'description': port.description,
                'hwid': port.hwid
            })
        
        return ports
    
    def get_available_baudrates(self) -> list:
        """
        @brief 获取可用的波特率列表
        @return list 可用波特率列表
        """
        return [1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600]
    
    def get_available_parities(self) -> list:
        """
        @brief 获取可用的校验位列表
        @return list 可用校验位列表
        """
        return [
            {'value': 'N', 'name': '无校验'},
            {'value': 'E', 'name': '偶校验'},
            {'value': 'O', 'name': '奇校验'}
        ]
    
    def get_available_system_modes(self) -> list:
        """
        @brief 获取可用的系统模式列表
        @return list 可用系统模式列表
        """
        return [
            {'value': 'independent_speed_closed_loop', 'name': '独立速度闭环'},
            {'value': 'independent_speed_open_loop', 'name': '独立速度开环'},
            {'value': 'same_source_speed_closed_loop', 'name': '同源速度闭环'},
            {'value': 'same_source_speed_open_loop', 'name': '同源速度开环'},
            {'value': 'differential_speed_closed_loop', 'name': '差速闭环'}
        ]
    
    def get_logging_config(self) -> Dict[str, Any]:
        """
        @brief 获取日志配置
        @return Dict[str, Any] 日志配置字典
        """
        try:
            logging_config_file = "config/logging_config.json"
            if os.path.exists(logging_config_file):
                with open(logging_config_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            else:
                # 返回默认日志配置
                return {
                    "log_mode": "info",
                    "log_to_file": True,
                    "log_to_console": True,
                    "max_file_size": 10485760,
                    "backup_count": 5,
                    "log_format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
                    "date_format": "%Y-%m-%d %H:%M:%S"
                }
        except Exception as e:
            logger.error(f"获取日志配置失败: {e}")
            return {}
    
    def set_logging_config(self, config: Dict[str, Any]) -> bool:
        """
        @brief 设置日志配置
        @param config 日志配置字典
        @return bool 是否设置成功
        """
        try:
            logging_config_file = "config/logging_config.json"
            with open(logging_config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, indent=4, ensure_ascii=False)
            logger.info("日志配置已更新")
            return True
        except Exception as e:
            logger.error(f"设置日志配置失败: {e}")
            return False
